﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine.Rendering;

namespace NinjaToolbox.PhysicsSystem
{
    public class OBBBoxSceneGUIDrawer
    {
        bool mIsInitialized;
        bool mEnabled;
        Func<OBBBox> mObbBoxFunc;

        public event Action<OBBBox> OnObbBoxChanged;
        public bool IsInitialized { get { return mIsInitialized; } }
        public bool Enabled { get { return mEnabled; } set { mEnabled = value; } }


        public void Initialization(Func<OBBBox> obbBoxFunc)
        {
            mObbBoxFunc = obbBoxFunc;
            SceneView.onSceneGUIDelegate += DrawSceneGUI;
            mIsInitialized = true;
        }

        public void Dispose()
        {
            mIsInitialized = false;
            SceneView.onSceneGUIDelegate -= DrawSceneGUI;
        }

        public void DrawInspectorGUI()
        {
            var rect = EditorGUILayout.GetControlRect();
            var value = GUI.Toggle(rect, mEnabled, "Enable Handle", EditorStyles.miniButton);
            if (value != mEnabled)
            {
                mEnabled = value;

                SceneView.RepaintAll();
            }
        }

        void DrawSceneGUI(SceneView sceneView)
        {
            if (!mEnabled) return;

            DrawHandleButtons();
        }

        void DrawHandleButtons()
        {
            if (Camera.current == null) return;

            var cacheColor = Handles.color;

            var right = mObbBoxFunc().matrix.rotation * Vector3.right;
            var up = mObbBoxFunc().matrix.rotation * Vector3.up;
            var forward = mObbBoxFunc().matrix.rotation * Vector3.forward;

            var cameraForward = Camera.current.transform.forward;

            var handleSizeScale = 0.035f;
            var handleMaxSize = 0.1f;
            var defaultGizmosColor = mObbBoxFunc().gizmosColor;
            var obbBox = mObbBoxFunc();

            var minPosition = obbBox.GetWorldPosition() - obbBox.size;
            var maxPosition = obbBox.GetWorldPosition() + obbBox.size;

            var point = obbBox.GetWorldPosition() + right * mObbBoxFunc().size.x * 0.5f;
            Handles.color = Vector3.Dot(cameraForward, right) < 0 ? defaultGizmosColor : new Color(defaultGizmosColor.r, defaultGizmosColor.g, defaultGizmosColor.b, 0.5f);
            var handleSize = Mathf.Min(HandleUtility.GetHandleSize(point) * handleSizeScale, handleMaxSize);
            var newPoint = Handles.FreeMoveHandle(GUIUtility.GetControlID(FocusType.Passive), point, Quaternion.identity, handleSize, Vector3.zero, Handles.DotHandleCap);//+x
            maxPosition.x = obbBox.matrix.inverse.MultiplyPoint3x4(newPoint).x;

            point = obbBox.GetWorldPosition() - right * mObbBoxFunc().size.x * 0.5f;
            Handles.color = Vector3.Dot(cameraForward, -right) < 0 ? defaultGizmosColor : new Color(defaultGizmosColor.r, defaultGizmosColor.g, defaultGizmosColor.b, 0.5f);
            handleSize = Mathf.Min(HandleUtility.GetHandleSize(point) * handleSizeScale, handleMaxSize);
            newPoint = Handles.FreeMoveHandle(GUIUtility.GetControlID(FocusType.Passive), point, Quaternion.identity, handleSize, Vector3.zero, Handles.DotHandleCap);//-x
            minPosition.x = obbBox.matrix.inverse.MultiplyPoint3x4(newPoint).x;

            point = obbBox.GetWorldPosition() + up * mObbBoxFunc().size.y * 0.5f;
            Handles.color = Vector3.Dot(cameraForward, up) < 0 ? defaultGizmosColor : new Color(defaultGizmosColor.r, defaultGizmosColor.g, defaultGizmosColor.b, 0.5f);
            handleSize = Mathf.Min(HandleUtility.GetHandleSize(point) * handleSizeScale, handleMaxSize);
            newPoint = Handles.FreeMoveHandle(GUIUtility.GetControlID(FocusType.Passive), point, Quaternion.identity, handleSize, Vector3.zero, Handles.DotHandleCap);//+y
            maxPosition.y = obbBox.matrix.inverse.MultiplyPoint3x4(newPoint).y;

            point = obbBox.GetWorldPosition() - up * mObbBoxFunc().size.y * 0.5f;
            Handles.color = Vector3.Dot(cameraForward, -up) < 0 ? defaultGizmosColor : new Color(defaultGizmosColor.r, defaultGizmosColor.g, defaultGizmosColor.b, 0.5f);
            handleSize = Mathf.Min(HandleUtility.GetHandleSize(point) * handleSizeScale, handleMaxSize);
            newPoint = Handles.FreeMoveHandle(GUIUtility.GetControlID(FocusType.Passive), point, Quaternion.identity, handleSize, Vector3.zero, Handles.DotHandleCap);//-y
            minPosition.y = obbBox.matrix.inverse.MultiplyPoint3x4(newPoint).y;

            point = obbBox.GetWorldPosition() + forward * mObbBoxFunc().size.z * 0.5f;
            Handles.color = Vector3.Dot(cameraForward, forward) < 0 ? defaultGizmosColor : new Color(defaultGizmosColor.r, defaultGizmosColor.g, defaultGizmosColor.b, 0.5f);
            handleSize = Mathf.Min(HandleUtility.GetHandleSize(point) * handleSizeScale, handleMaxSize);
            newPoint = Handles.FreeMoveHandle(GUIUtility.GetControlID(FocusType.Passive), point, Quaternion.identity, handleSize, Vector3.zero, Handles.DotHandleCap);//+z
            maxPosition.z = obbBox.matrix.inverse.MultiplyPoint3x4(newPoint).z;

            point = obbBox.GetWorldPosition() - forward * mObbBoxFunc().size.z * 0.5f;
            Handles.color = Vector3.Dot(cameraForward, -forward) < 0 ? defaultGizmosColor : new Color(defaultGizmosColor.r, defaultGizmosColor.g, defaultGizmosColor.b, 0.5f);
            handleSize = Mathf.Min(HandleUtility.GetHandleSize(point) * handleSizeScale, handleMaxSize);
            newPoint = Handles.FreeMoveHandle(GUIUtility.GetControlID(FocusType.Passive), point, Quaternion.identity, handleSize, Vector3.zero, Handles.DotHandleCap);//-z
            minPosition.z = obbBox.matrix.inverse.MultiplyPoint3x4(newPoint).z;

            obbBox.offset = (maxPosition + minPosition) * 0.5f;
            obbBox.size = (maxPosition - minPosition);

            if (OnObbBoxChanged != null)
                OnObbBoxChanged(obbBox);

            Handles.color = cacheColor;
        }
    }
}
